home *** CD-ROM | disk | FTP | other *** search
-
-
- /*
- ADDENTRY.C Function PbAddEntry: Adds an entry (individual or group) to an
- open phonebook.
-
- INPUT: Phonebook structure and filled phonebook entry structure.
-
- OUTPUT: If successful, updates the entries field of the phonebook
- structure, and sets the ID field of the entry structure.
- */
-
- #include <stdio.h>
- #include <io.h>
- #include <string.h>
- #include <malloc.h>
- #include <phonebk.h>
-
- int pascal PbModifyEntry(PB *pb, int RecordID, PBE *new_entry)
- {
- PBE *old_entry = NULL, *group_entry = NULL;
- PBEFIXED fixed_part;
- char *entry_buffer;
- int result;
- int filenum;
- int i, j; /* loop counters */
- long PbSize, offset;
- BYTE hw_type,
- hasccc = HASCCC; /* for changing the h/w type of a group */
- int red, writ; /* for checking returns from fread() and fwrite() */
- int buffed_rids = pb->OBufferSize/sizeof(LONGWORD); /* whether 0 or not */
- int temperrno = 0; /* for saving aside Pberrno */
-
- Pberrno = 0; /* Initially, always reset */
-
- /* First, check params */
- if ((pb == NULL) ||
- (new_entry == NULL)) {
- Pberrno = INVALIDPARAMETER;
- goto error_out;
- }
- if ((RecordID < 0) ||
- (RecordID > 999)) {
- Pberrno = INVALIDPARAMETER;
- return(NULL);
- }
-
- /* Allocate memory for and fetch the record being changed */
- old_entry = PbGetEntry(pb, NULL, NULL, RecordID);
- if (!old_entry) {
- Pberrno = NOENTRYPRESENT;
- goto error_out;
- }
-
- /* call EntryOkToChange(); if not, free the old_entry and get out */
- if ((!(entry_buffer = EntryOkToChange(pb, old_entry, new_entry)))) {
- Pberrno = INVALIDCHANGE;
- goto error_out;
- }
-
- /* If new entry is larger than old, put it at end of file */
- if (new_entry->length > old_entry->length) {
-
- /* Next, find the offset of the end-of-file , and set a vbl offset to it */
- filenum = fileno(pb->fp);
- PbSize = filelength(filenum);
- if (PbSize == -1L) {
- Pberrno = FILELENGTHERROR;
- goto error_out;
- }
- offset = PbSize;
-
- /* Attempt the append to file */
- if (fseek(pb->fp, 0L, SEEK_END)) {
- Pberrno = FSEEKERROR;
- goto error_out;
- }
- writ = fwrite(entry_buffer, new_entry->length, 1, pb->fp);
-
- if (writ != 1) {
- Pberrno = CANTWRITE;
- goto error_out;
- }
-
- /* If write successful, change the offset at RID and unused_bytes field */
- else {
-
- /* If the RID is in the OBuffer, change the offset there first */
- if (pb->OBuffer) {
- if ((RecordID >= pb->FirstOBufferRID) &&
- (RecordID < pb->FirstOBufferRID + buffed_rids)) {
- pb->OBuffer[RecordID - pb->FirstOBufferRID] = offset;
- }
- }
-
- /* Write the changed offset to the file */
- if (fseek(pb->fp, 160L + RecordID*sizeof(LONGWORD), SEEK_SET)) {
- Pberrno = FSEEKERROR;
- goto error_out;
- }
- writ = fwrite(&offset, sizeof(LONGWORD), 1, pb->fp);
- if (writ != 1) {
- Pberrno = CANTWRITE;
- goto error_out;
- }
-
- /* Add size of old entry to the FreeBytes field */
- pb->header.FreeBytes += old_entry->length;
- }
- }
-
- /* The new entry is smaller, or the same size */
- else {
-
- /* Otherwise, just write the new entry where the old entry was */
-
- /* First, there is STILL a possibility of freeing too many bytes */
- if ((old_entry->length - new_entry->length + pb->header.FreeBytes)
- > MAXUNUSEDBYTES) {
- Pberrno = TOOMANYFREEBYTES;
- goto error_out;
- }
- else {
- pb->header.FreeBytes += old_entry->length - new_entry->length;
- }
-
- /* First, find offset of old entry */
- /* no error possible, since we've gotten it already */
- offset = OffsetOfEntry(pb, RecordID);
-
- /* ...and seek to there and write the new entry in */
- if (fseek(pb->fp, offset, SEEK_SET)) {
- Pberrno = FSEEKERROR;
- goto error_out;
- }
- writ = fwrite(entry_buffer, new_entry->length, 1, pb->fp);
-
- /* If write not successful, free the memory used for old entry, and quit */
- if (writ != 1) {
- Pberrno = CANTWRITE;
- goto error_out;
- }
- }
-
- /* If size changed at all, "free bytes" was updated, so write it to file */
- if (old_entry->length != new_entry->length) {
- if (fseek(pb->fp, 6L, SEEK_SET)) {
- Pberrno = FSEEKERROR;
- goto error_out;
- }
- writ = fwrite(&pb->header.FreeBytes, sizeof(int), 1, pb->fp);
- if (writ != 1) {
- Pberrno = CANTWRITE;
- goto error_out;
- }
- }
-
- /* If hardware type is being changed, check out all groups that entry is a
- member of: IF change is CCP-to-FaxOnly, AND any group is CCP, change
- that group to FaxOnly. IF change is FaxOnly-to-CCP, any groups should
- be FaxOnly. (If any AREN'T, set them and set a warning.) For any
- such groups, scan their other members, looking for the first FaxOnly.
- IF any found, leave the group FaxOnly. ELSE, set it to CCP. */
- if (old_entry->HardwareType != new_entry->HardwareType) {
-
- /* If the change is to FAXONLY, make sure all groups involved be FAXONLY */
- if (new_entry->HardwareType == FAXONLY) {
- for (i=0; i<new_entry->members; i++) {
- if (HardwareTypeOf(pb, new_entry->MemberList[i], &offset) == HASCCC) {
- if (fseek(pb->fp, offset, SEEK_SET)) {
- Pberrno = FSEEKERROR;
- goto error_out;
- }
- writ = fwrite(&new_entry->HardwareType, sizeof(BYTE), 1, pb->fp);
- if (writ != 1) {
- Pberrno = CANTWRITE;
- goto error_out;
- }
- }
- }
- }
-
- /* If change is FAXONLY to HASCCC there is even MORE work to do!
- Every group involved should have been FAXONLY: check all their OTHER
- members. If they are all HASCCC, then change group to HASCCC */
- else {
- for (i=0; i<new_entry->members; i++) {
- group_entry = PbGetEntry(pb, NULL, NULL, new_entry->MemberList[i]);
- for (j=0; j<group_entry->members; j++) {
-
- /* check all members other than ours */
- if (group_entry->MemberList[j] != RecordID) {
- if (HardwareTypeOf(pb,
- group_entry->MemberList[j],
- &offset) == FAXONLY) {
- break;
- }
- }
- }
- if (j == group_entry->members) { /* they were all CCP except ours */
- offset = OffsetOfEntry(pb, new_entry->MemberList[i]) + 7L;
- if (fseek(pb->fp, offset, SEEK_SET)) {
- Pberrno = FSEEKERROR;
- goto error_out;
- }
- writ = fwrite(&hasccc, sizeof(BYTE), 1, pb->fp);
- if (writ != 1) {
- Pberrno = CANTWRITE;
- goto error_out;
- }
- } /* end of scanning other members of group the entry is member of */
- } /* end of scanning all the group the entry is a member of */
- } /* end of if change is FAXONLY to HASCCC */
- } /* end of if hardware types differ */
-
- /* and if we got here without any goto, all was well! */
- PbFreePBE(pb, old_entry);
- free(entry_buffer);
- return(SUCCESS);
- error_out:
- if (Pberrno) {
- temperrno = Pberrno;
- }
- if (old_entry) {
- PbFreePBE(pb, old_entry);
- }
- if (group_entry) {
- PbFreePBE(pb, group_entry);
- }
- if (temperrno) {
- Pberrno = temperrno;
- }
- if (entry_buffer) {
- free(entry_buffer);
- }
- return(FAIL);
- }